package roborl;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Vector;

import net.phys2d.raw.ActuatorJoint;
import net.phys2d.raw.Body;

public abstract class PhysRobot implements Robot {
	public boolean readOnly;
	protected Vector<Object> parts;
	// Sensor sensor;
	protected Vector<Body> acutator;
	protected int DECISION_ITERATION = 40;
	protected int SILENT_ITERATION = 15;
	protected int STORE_ITERATION = 500;
	protected Decision decision;
	protected int decision_count;
	protected RobotState lastState;
	public boolean autoSave;
	public static final Action none = new Action("None");

	public double averageReward, fallRate;

	public void store() {
		File f = new File(this.getClass().getName());
		try {
			synchronized (decision) {
				ObjectOutputStream objectOutputStream = new ObjectOutputStream(
						new FileOutputStream(f));
				objectOutputStream.writeObject(decision.getApproximate());
				objectOutputStream.close();
				System.out.println("Store----");
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void read(String file) {
		File f = new File(file);
		try {
			ObjectInputStream inputStream = new ObjectInputStream(
					new FileInputStream(f));
			decision
					.setApproximate((ValueApproximate) inputStream.readObject());
			inputStream.close();
			System.out.println("Read----" + f.getName());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void read() {
		read(this.getClass().getName());
	}

	public PhysRobot() {

		parts = new Vector<Object>();
		// sensor = new PhysSensor();
		acutator = new Vector<Body>();
		decision_count = 0;
		randomRate = 1;
		autoSave = true;
		readOnly = false;
		averageReward = 0.0f;
		fallRate = 0.99f;
		cRate = 0.2f;
	}

	public double cRate;

	public abstract RobotState getState();

	public abstract Vector<Action> getAvailableActions();

	public double randomRate;
	private int store_count;
	public int achieve = 0;

	protected void update() {
		decision_count--;
		store_count--;
		if (store_count < 0) {
			store_count = STORE_ITERATION;
			if (!readOnly && autoSave)
				store();
		}
		if (decision_count < 0 && decision != null) {
			decision_count = DECISION_ITERATION + SILENT_ITERATION;
			RobotState current = getState();
			double rewd = 0.0;
			if (lastState != null && lastAction != null && !readOnly) {
				rewd = decision.learn(lastState, current, lastAction, cRate,
						0.8f);

			}

			if (lastState != null && lastAction != null) {
				rewd = decision.rewards.getReward(lastState, current);
				averageReward = averageReward * fallRate + (1.0f - fallRate)
						* rewd;
				// System.out.println("Avg award: " + averageReward);
			}

			lastState = current;
			if (!readOnly) {
				takeActionP(decision.getAction(current, randomRate,
						getAvailableActions()));
				randomRate *= 0.99;
			} else {
				takeActionP(decision.getAction(current, 0,
						getAvailableActions()));
			}
			// System.out.println(lastAction + " " + randomRate + " " + rewd);
		} else if (decision_count < SILENT_ITERATION) {
			takeAction(none);
		}
		simpleUpdate();
	}

	public void init() {

	}

	protected abstract void simpleUpdate();

	protected Action lastAction;

	public abstract void takeAction(Action action);

	public void takeActionP(Action action) {
		takeAction(action);
		lastAction = action;
	}

	public Vector<Object> getParts() {
		return parts;
	}

	public Vector<Body> getAcutator() {
		return acutator;
	}

	public double getRandomRate() {
		return randomRate;
	}

	public void setRandomRate(double randomRate) {
		this.randomRate = randomRate;
	}

	public Decision getDecision() {
		return decision;
	}

	public void setDecision(Decision decision) {
		this.decision = decision;
	}

}
